package com.kexilo.system.management.controller.monitor;

import com.kexilo.core.common.core.page.TableDataInfo;
import com.kexilo.core.common.core.web.domain.R;
import com.kexilo.core.common.utils.SecurityUtils;
import com.kexilo.core.common.utils.StringUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 在线用户监控
 * 
 * @author Kexilo
 */
@RestController
@RequestMapping("/monitor/online")
@Tag(name = "在线用户监控", description = "在线用户监控相关接口")
public class OnlineController {
    
    private static final Logger log = LoggerFactory.getLogger(OnlineController.class);

    @Autowired(required = false)
    private RedisTemplate<String, Object> redisTemplate;

    private static final String LOGIN_TOKEN_KEY = "login_tokens:";

    /**
     * 获取在线用户列表
     */
    @PreAuthorize("@ss.hasPermi('monitor:online:list')")
    @GetMapping("/list")
    @Operation(summary = "获取在线用户列表", description = "获取当前在线用户列表")
    public TableDataInfo list(
            @RequestParam(required = false) String ipaddr,
            @RequestParam(required = false) String userName) {
        
        List<Map<String, Object>> onlineUsers = new ArrayList<>();
        
        if (redisTemplate == null) {
            return new TableDataInfo(onlineUsers, 0);
        }

        try {
            // 获取所有登录token
            Set<String> keys = redisTemplate.keys(LOGIN_TOKEN_KEY + "*");
            if (keys != null) {
                for (String key : keys) {
                    try {
                        Object loginUser = redisTemplate.opsForValue().get(key);
                        if (loginUser != null) {
                            Map<String, Object> userInfo = convertToUserInfo(key, loginUser);
                            
                            // 过滤条件
                            if (StringUtils.isNotEmpty(ipaddr) && 
                                !userInfo.get("ipaddr").toString().contains(ipaddr)) {
                                continue;
                            }
                            if (StringUtils.isNotEmpty(userName) && 
                                !userInfo.get("userName").toString().contains(userName)) {
                                continue;
                            }
                            
                            onlineUsers.add(userInfo);
                        }
                    } catch (Exception e) {
                        log.warn("处理在线用户信息失败: {}", e.getMessage());
                    }
                }
            }
        } catch (Exception e) {
            log.error("获取在线用户列表失败", e);
        }

        // 按登录时间排序
        onlineUsers.sort((a, b) -> {
            String timeA = (String) a.get("loginTime");
            String timeB = (String) b.get("loginTime");
            return timeB.compareTo(timeA);
        });

        return new TableDataInfo(onlineUsers, onlineUsers.size());
    }

    /**
     * 强制退出用户
     */
    @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
    @DeleteMapping("/{tokenId}")
    @Operation(summary = "强制退出用户", description = "强制指定用户退出登录")
    public R<Void> forceLogout(@Parameter(description = "Token ID") @PathVariable String tokenId) {
        if (redisTemplate == null) {
            return R.fail("Redis未配置");
        }

        try {
            String key = LOGIN_TOKEN_KEY + tokenId;
            Object loginUser = redisTemplate.opsForValue().get(key);
            
            if (loginUser != null) {
                redisTemplate.delete(key);
                log.info("管理员强制退出用户: {}", tokenId);
                return R.success("强制退出成功");
            } else {
                return R.fail("用户已离线");
            }
        } catch (Exception e) {
            log.error("强制退出用户失败", e);
            return R.fail("强制退出失败");
        }
    }

    /**
     * 批量强制退出用户
     */
    @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
    @DeleteMapping("/batch/{tokenIds}")
    @Operation(summary = "批量强制退出用户", description = "批量强制指定用户退出登录")
    public R<Void> batchForceLogout(@Parameter(description = "Token ID列表") @PathVariable String tokenIds) {
        if (redisTemplate == null) {
            return R.fail("Redis未配置");
        }

        try {
            String[] tokenArray = tokenIds.split(",");
            List<String> keys = new ArrayList<>();
            
            for (String tokenId : tokenArray) {
                keys.add(LOGIN_TOKEN_KEY + tokenId);
            }
            
            Long deletedCount = redisTemplate.delete(keys);
            log.info("管理员批量强制退出用户，成功: {}, 总数: {}", deletedCount, tokenArray.length);
            
            return R.success("批量强制退出成功，退出用户数: " + deletedCount);
        } catch (Exception e) {
            log.error("批量强制退出用户失败", e);
            return R.fail("批量强制退出失败");
        }
    }

    /**
     * 获取在线用户统计
     */
    @PreAuthorize("@ss.hasPermi('monitor:online:list')")
    @GetMapping("/stats")
    @Operation(summary = "获取在线用户统计", description = "获取在线用户统计信息")
    public R<Map<String, Object>> getOnlineStats() {
        Map<String, Object> stats = new HashMap<>();
        
        if (redisTemplate == null) {
            stats.put("total", 0);
            stats.put("today", 0);
            return R.success(stats);
        }

        try {
            // 总在线用户数
            Set<String> keys = redisTemplate.keys(LOGIN_TOKEN_KEY + "*");
            int totalOnline = keys != null ? keys.size() : 0;
            
            // 今日登录用户数（这里简化处理，实际应该从登录日志获取）
            int todayLogin = 0;
            
            stats.put("total", totalOnline);
            stats.put("today", todayLogin);
            stats.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            
            return R.success(stats);
        } catch (Exception e) {
            log.error("获取在线用户统计失败", e);
            return R.fail("获取在线用户统计失败");
        }
    }

    /**
     * 转换为用户信息
     */
    private Map<String, Object> convertToUserInfo(String key, Object loginUser) {
        Map<String, Object> userInfo = new HashMap<>();
        
        try {
            // 从key中提取tokenId
            String tokenId = key.replace(LOGIN_TOKEN_KEY, "");
            userInfo.put("tokenId", tokenId);
            
            // 从Redis获取过期时间
            Long expire = redisTemplate.getExpire(key, TimeUnit.SECONDS);
            userInfo.put("expireTime", expire != null ? expire : 0);
            
            // 这里应该从LoginUser对象中提取信息，暂时使用模拟数据
            // 实际应该根据LoginUser的结构来解析
            userInfo.put("userName", "user_" + tokenId.substring(0, 8));
            userInfo.put("deptName", "默认部门");
            userInfo.put("ipaddr", "127.0.0.1");
            userInfo.put("loginLocation", "本地");
            userInfo.put("browser", "Chrome");
            userInfo.put("os", "Windows 10");
            userInfo.put("loginTime", LocalDateTime.now().minusMinutes(
                (int) (Math.random() * 120)).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            
        } catch (Exception e) {
            log.warn("转换用户信息失败: {}", e.getMessage());
            userInfo.put("tokenId", "unknown");
            userInfo.put("userName", "unknown");
            userInfo.put("ipaddr", "unknown");
        }
        
        return userInfo;
    }
}

